package com.bootdo.app.service.impl;

import com.bootdo.app.common.aop.exception.ExceptionEnum;
import com.bootdo.app.common.aop.exception.MiniprogramException;
import com.bootdo.app.common.aop.exception.WXException;
import com.bootdo.app.common.utils.ContextHandlerUtil;
import com.bootdo.app.common.utils.IDGenerator;
import com.bootdo.app.common.utils.StateUtil;
import com.bootdo.app.config.WXConfig;
import com.bootdo.app.dto.wx.TemplateMsgRequest;
import com.bootdo.app.dto.wx.TransferMoneyRequest;
import com.bootdo.app.service.UserCashOutService;
import com.bootdo.app.service.WXService;
import com.bootdo.app.vo.miniprogram.UserCashOutVo;
import com.bootdo.app.vo.wx.TransferMoneyResponse;
import com.bootdo.common.utils.DateUtils;
import com.bootdo.system.dao.UserDao;
import com.bootdo.system.domain.TbWallet;
import com.bootdo.system.domain.TbWeixinconfig;
import com.bootdo.system.domain.TbWithdrawal;
import com.bootdo.system.domain.TbWxmenu;
import com.bootdo.system.domain.TbWxuser;
import com.bootdo.system.domain.UserDO;
import com.bootdo.system.mapper.TbWithdrawalMapper;
import com.bootdo.system.service.WalletService;
import com.bootdo.system.service.WxConfigService;
import com.bootdo.system.service.WxMenuService;
import com.bootdo.system.service.WxUserService;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @auther: Along
 * @description: 用户提现
 */
@Slf4j
@Service
public class UserCashOutServiceImpl implements UserCashOutService {

    // 钱包配置
    @Autowired
    private WalletService walletService;
    
    @Autowired
	private WXService wXService;
    
    @Autowired
	private WxConfigService wxConfigService;
    // 提现记录
    @Autowired
    private TbWithdrawalMapper withdrawalMapper;
    // 微信用户
    @Autowired
    private WxUserService wxUserService;
    // sys_user
    @Autowired
    private UserDao userDao;

    @Autowired
    private WXService wxService;
    
    @Autowired
	private WxMenuService wxMenuService;

    /**
     * 提现
     * @param amount 提现金额 （单位：元）
     */
    @Transactional
    @Override
    public void cashOut(String amount) {
        Integer amount_int;
        try {
            amount_int = Integer.valueOf(amount) * 100; // 将元转换成分
            if(amount_int < 100 || amount_int > 500000){
                throw new MiniprogramException(ExceptionEnum.MINI_PROGRAM_CASH_OUT_AMOUNT_GT_100_LT_500000);
            }
            // 获取钱包配置，校验
            TbWallet wall = walletService.getWall();
            if(wall != null){
                // 提现间隔时间
                Integer jgsj = wall.getJgsj();
                // 提现最小金额(单位：元)
                Integer zxje = wall.getZxje();
                if(amount_int < zxje * 100){
                    Integer code = ExceptionEnum.MINI_PROGRAM_CASH_OUT_AMOUNT_MSG_ZXJE.getCode();
                    String msg = ExceptionEnum.MINI_PROGRAM_CASH_OUT_AMOUNT_MSG_ZXJE.getMsg().replace("?", zxje.toString());
                    throw new MiniprogramException(code,msg);
                }
                // 获取提现记录，校验
                TbWithdrawal tbWithdrawal = withdrawalMapper.selectLastOneByUserId(Integer.valueOf(ContextHandlerUtil.getCurrentUserId()));
                if(tbWithdrawal != null){ // 说明有提现记录，否则，没有则可以直接提现
                	long createtime=0;
                	String createtime2 = tbWithdrawal.getCreatetime();
                	if(createtime2.contains(":")) {
            			Date parseDate = DateUtils.parseDate(createtime2);
            			createtime = parseDate.getTime();
            		}else {
            			createtime = Long.parseLong(createtime2);
            		}
//                  long now = System.currentTimeMillis() / 1000;
                	long now = new Date().getTime();
                    long addTime = jgsj * 60000;
                    if(now < createtime + addTime){
                        Integer code = ExceptionEnum.MINI_PROGRAM_CASH_OUT_AMOUNT_MSG_JGSJ.getCode();
                        String msg = ExceptionEnum.MINI_PROGRAM_CASH_OUT_AMOUNT_MSG_JGSJ.getMsg().replace("?", jgsj.toString());
                        throw new MiniprogramException(code,msg);
                    }
                }
            }
        }catch (NumberFormatException e){
            throw new MiniprogramException(ExceptionEnum.MINI_PROGRAM_CASH_OUT_AMOUNT_ERROR);
        }
        // 可以正常提现,提现前判断彼此余额是否充足
        BigDecimal amountDecimal = new BigDecimal(amount);
        Integer userId = Integer.valueOf(ContextHandlerUtil.getCurrentUserId());
        String openId = ContextHandlerUtil.getOpenId();
//        TbWxuser userById = wxUserService.getUserById(openId);
        // 微信用户,判断用户账户余额是否充足
        TbWxuser wxuser = wxUserService.getById(userId);
        BigDecimal wxuserBalance = new BigDecimal(wxuser.getBalance());
        if(amountDecimal.compareTo(wxuserBalance) > 0){
            throw new MiniprogramException(ExceptionEnum.MINI_PROGRAM_CASH_OUT_BALANCE_NOT_ENOUGH);
        }
        // 代理商,判断代理商余额是否充足
        UserDO userDO = userDao.get(Long.valueOf(wxuser.getSid()));
        BigDecimal userDoBalance = new BigDecimal(userDO.getBalance());
        if(amountDecimal.compareTo(userDoBalance) > 0){
            throw new MiniprogramException(ExceptionEnum.MINI_PROGRAM_CASH_OUT_ERROR);
        }
        // 数据库保存提现记录
        TbWithdrawal withdrawal = new TbWithdrawal();
        withdrawal.setAdminId(Integer.valueOf(wxuser.getSid()));
        withdrawal.setWxuserId(userId);
        withdrawal.setCash(amount); // 数据库存储单位：元
        withdrawal.setCreatetime(DateUtils.format(new Date()));
        withdrawal.setUpdatetime(DateUtils.format(new Date()));
        withdrawal.setStatus(0);
        withdrawal.setDlName(userDO.getName()); // 代理名称
        withdrawal.setWxName(wxuser.getNickname()); // 微信用户昵称
        withdrawalMapper.insertSelective(withdrawal);
        // 走微信提现
        TransferMoneyResponse transferMoneyResponse;
        synchronized (""){
            TransferMoneyRequest request = new TransferMoneyRequest();
//            request.setMch_appid("wx27561fe9322705ce"); // 商户账号appid  (必需)
            request.setMch_appid(WXConfig.getWxPayMchAppId()); // 商户账号appid  (必需)
//            request.setMchid("1554095611"); // 商户号  (必需)
            request.setMchid(WXConfig.getWxPayMchId()); // 商户号  (必需)
            request.setNonce_str(StateUtil.getStateStr()); // 随机字符串 不长于32位 (必需)
            request.setPartner_trade_no(String.valueOf(withdrawal.getId())); // 商户订单号 (必需) (商户订单号，需保持唯一性(只能是字母或者数字，不能包含有其它字符))
            request.setOpenid(wxuser.getOpenid()); // 用户openid (必需)
            request.setAmount(amount_int); // 金额 (必需) (企业付款金额，单位为分)
            request.setDesc(userDO.getName() + "转账给" + wxuser.getNickname() + amount_int / 100 +"元"); // 企业付款备注 (必需) （企业付款备注，必填。注意：备注中的敏感词会被转成字符*）
            transferMoneyResponse = wxService.transferMoneyToUser(request);
            log.info("微信付款到零钱请求结果: transferMoneyResponse = {}",transferMoneyResponse);
        }
        if(transferMoneyResponse == null){
            throw new WXException(ExceptionEnum.WX_REQUEST_ERROR);
        }
        // 付款成功
        if(transferMoneyResponse.getReturn_code().equals("SUCCESS") && transferMoneyResponse.getResult_code().equals("SUCCESS")){
            String partner_trade_no = transferMoneyResponse.getPartner_trade_no(); // 商户订单号
            String payment_time = transferMoneyResponse.getPayment_time();
            // 更新提现记录表状态
            TbWithdrawal update_withdrawal = new TbWithdrawal();
            update_withdrawal.setId(Integer.valueOf(partner_trade_no));
            update_withdrawal.setStatus(1);
            update_withdrawal.setUpdatetime(DateUtils.format(new Date()));
            withdrawalMapper.updateByPrimaryKeySelective(update_withdrawal);
            // 扣除用户余额（单位：元）
            BigDecimal wxUserBalance = new BigDecimal(wxuser.getBalance());
            BigDecimal wxUserUpdateBalance = wxUserBalance.subtract(amountDecimal);
            TbWxuser update_tbWxuser = new TbWxuser();
            update_tbWxuser.setId(userId);
            update_tbWxuser.setBalance(wxUserUpdateBalance.toString());
            wxUserService.insert2update(update_tbWxuser);
            // 扣除代理余额（单位：元）
            BigDecimal userDobalance = new BigDecimal(userDO.getBalance());
            BigDecimal userDoUpdateBalance = userDobalance.subtract(amountDecimal);
            UserDO update_UserDo = new UserDO();
            update_UserDo.setUserId(userDO.getUserId());
            update_UserDo.setBalance(userDoUpdateBalance.toString());
            userDao.update(update_UserDo);
            
          //发送模板消息 String toUserOpenId,String url,String changeTime,String changeInfo,String changeAmount,String nowBalance
			if(wxuser.getGzhOpenId() != null) {
				Long userId2 = userDO.getUserId();
	    		TbWeixinconfig selectByUserId = wxConfigService.selectByUserId(userId2.intValue());
	    		TbWxmenu selectByUserId2 = wxMenuService.selectByUserId(userId2.intValue());
				TemplateMsgRequest newUserJoin = TemplateMsgRequest.createBalanceChange(wxuser.getGzhOpenId(),null, DateUtils.format(new Date()), "用户提现",amount,wxUserUpdateBalance.toString(),selectByUserId.getServiceTemplate3());
	            wXService.sendTemplateMsg(selectByUserId2.getAppid(), selectByUserId2.getAppsecret(), newUserJoin);
			}
        }else {
        	throw new WXException(500,transferMoneyResponse.getErr_code_des());
        }
    }

    @Override
    public List<UserCashOutVo> getCashOutList() {
        String currentUserId = ContextHandlerUtil.getCurrentUserId();
        return withdrawalMapper.getCashOutList(Integer.valueOf(currentUserId));
    }

    @Override
    public int count() {
        return withdrawalMapper.count(null);
    }

	@Override
	public List<UserCashOutVo> getCashOutList2() {
		  String currentUserId = ContextHandlerUtil.getCurrentUserId();
		  String date=DateUtils.format3(new Date());
	      return withdrawalMapper.getCashOutList2(Integer.valueOf(currentUserId), date);
	}
}
